/*********************************************************************
*
*  http_net_print.h file generation and dynamic variable parsing.
*
**********************************************************************
* File Name:       DynVar.java
* Complier:        JAVA version "1.6.0_20 and onwards"
* IDE :            NetBeans
*/

/*
Copyright (C) 2012-2023, Microchip Technology Inc., and its subsidiaries. All rights reserved.

The software and documentation is provided by microchip and its contributors
"as is" and any express, implied or statutory warranties, including, but not
limited to, the implied warranties of merchantability, fitness for a particular
purpose and non-infringement of third party intellectual property rights are
disclaimed to the fullest extent permitted by law. In no event shall microchip
or its contributors be liable for any direct, indirect, incidental, special,
exemplary, or consequential damages (including, but not limited to, procurement
of substitute goods or services; loss of use, data, or profits; or business
interruption) however caused and on any theory of liability, whether in contract,
strict liability, or tort (including negligence or otherwise) arising in any way
out of the use of the software and documentation, even if advised of the
possibility of such damage.

Except as expressly permitted hereunder and subject to the applicable license terms
for any third-party software incorporated in the software and any applicable open
source software license terms, no license or other rights, whether express or
implied, are granted under any patent or other intellectual property rights of
Microchip or any third party.
*/

package MicrochipMPFS;

import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.*;

public class DynVar {
    int offSetCounter = 0;
    int parseItrtn = 0;
    int tempFileRcrdLen = 0;
    boolean tcpipHttpNetVersionused;

    String regEx = "~(inc:[A-Za-z0-9\\ \\.-_\\/]{1,60}|[A-Za-z0-9_]{0,40}(\\([A-Za-z0-9_,\\ ]*\\))?)~";
    String ignore_dynmicvar_regEx = "<code>[\\ ]{0,1}~(inc:[A-Za-z0-9\\ \\.-_\\/]{1,60}|[A-Za-z0-9_]{0,40}(\\([A-Za-z0-9_,\\ ]*\\))?)~[\\ ]{0,1}</code>";
    private static List<DynamicVariable> vars;
    private Pattern parser = Pattern.compile(regEx);
    private Pattern ignore_dynmicvar_parser = Pattern.compile(ignore_dynmicvar_regEx);
    private String projectDir;

    String HTTPPRINT_NET_H_HEADER =
        "/*********************************************************************\r\n"+
        "* File Name: http_net_print.h\r\n"+
        "*\r\n"+
        "* Provides callback headers and resolution for user's custom\r\n"+
        "* HTTP NET Application.\r\n"+
        "* \r\n"+
        "* This file is automatically generated by the MPFS Utility\r\n"+
        "* ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR\r\n"+
        "* \r\n"+
       "*********************************************************************/\r\n"+

       "\r\n/*****************************************************************************\r\n"+
        "Copyright (C) 2012-2018 Microchip Technology Inc. and its subsidiaries.\r\n"+

       "\r\nMicrochip Technology Inc. and its subsidiaries.\r\n"+

       "\r\nSubject to your compliance with these terms, you may use Microchip software \r\n"+
       "and any derivatives exclusively with Microchip products. It is your\r\n"+
       "responsibility to comply with third party license terms applicable to your\r\n"+
       "use of third party software (including open source software) that may\r\n"+
       "accompany Microchip software.\r\n"+
       "\r\n" +     
       "THIS SOFTWARE IS SUPPLIED BY MICROCHIP \"AS IS\". NO WARRANTIES, WHETHER\r\n"+
       "EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED\r\n"+
       "WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR\r\n"+
       "PURPOSE.\r\n"+
       "\r\n" +    
       "IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,\r\n"+
       "INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND\r\n"+
       "WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS\r\n"+
       "BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE\r\n"+
       "FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN\r\n"+
       "ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,\r\n"+
       "THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.\r\n"+   
       "*****************************************************************************/\r\n"+
       "\r\n" +       
       "#ifndef _HTTP_NET_PRINT_H\r\n"+
       "#define _HTTP_NET_PRINT_H\r\n"+
       "\r\n/****************************************************************************\r\n"+
       "Section:\r\n"+
           "\tDynamic Variables Function Prototypes\r\n"+
       "\r\n" +       
       "Remarks:\r\n"+
           "\tThere are no predefined functions that do the dynamic variables processing.\r\n"+
           "\tThe only interface between the application and the HTTP module is done using\r\n"+
           "\tTCPIP_HTTP_NET_UserHandlerRegister() call.\r\n"+
           "\tTherefore, whenever the HTTP module will encounter a dynamic variable it will\r\n"+
           "\tsimply call the \"dynamicPrint\" function that was registered!\r\n"+
           "\tIt is up to the application to detect what dynamic variable is processed by\r\n"+
           "\texamining the TCPIP_HTTP_DYN_VAR_DCPT *parameter that's passed to the function\r\n"+
           "\tand take appropriate action.\r\n"+
           "\r\n" +  
           "\tThe mpfs generator does not generate a list of dynamic variables functions anymore.\r\n"+
           "\tAll the dynamic variable processing happens at run time!\r\n"+
           "\tWeb pages could be changed at run time and the web server will work just fine\r\n"+
           "\t(providing that the application properly processes the dynamic variables).\r\n"+
           "\r\n" +  
           "\tThese are just functions  belonging to the application.\r\n"+
           "\tThey can have any name the application uses to.\r\n"+
        "****************************************************************************/\r\n\r\n";
    String HTTPPRINT_NET_H_MIDDLE =
        "\r\n/*****************************************************************************\r\n"+
        "  Function:\r\n"+
        "    TCPIP_HTTP_NET_IO_RESULT TCPIP_HTTP_NET_ConnectionGetExecute(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack)\r\n"+
        "\r\n"+    
        "  Internal:\r\n"+
        "    See documentation in the TCP/IP Stack APIs or http_net.h for details.\r\n"+
        "****************************************************************************/\r\n"+
        "TCPIP_HTTP_NET_IO_RESULT TCPIP_HTTP_NET_ConnectionGetExecute(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack);\r\n"+
        "\r\n"+    
        "/*****************************************************************************\r\n"+
        "  Function:\r\n"+
        "    TCPIP_HTTP_NET_IO_RESULT TCPIP_HTTP_NET_ConnectionPostExecute(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack)\r\n"+
        "\r\n"+
        "  Internal:\r\n"+
        "    See documentation in the TCP/IP Stack APIs or http_net.h for details.\r\n"+
        "****************************************************************************/\r\n"+
        "TCPIP_HTTP_NET_IO_RESULT TCPIP_HTTP_NET_ConnectionPostExecute(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack);\r\n"+
        "\r\n"+    
        "/*****************************************************************************\r\n"+
        "  Function:\r\n"+
        "    uint8_t TCPIP_HTTP_NET_ConnectionFileAuthenticate(TCPIP_HTTP_NET_CONN_HANDLE connHandle, uint8_t *cFile, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack)\r\n"+
        "\r\n"+    
        "  Internal:\r\n"+
        "    See documentation in the TCP/IP Stack APIs or http_net.h for details.\r\n"+
        "****************************************************************************/\r\n"+
        "#if defined(TCPIP_HTTP_NET_USE_AUTHENTICATION)\r\n"+
        "uint8_t TCPIP_HTTP_NET_ConnectionFileAuthenticate(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const char *cFile, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack);\r\n"+
        "\r\n"+    
        "\r\n"+ 
        "/*****************************************************************************\r\n"+
        "  Function:\r\n"+
        "    uint8_t TCPIP_HTTP_NET_ConnectionUserAuthenticate(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const char *cUser, const char *cPass, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack)\r\n"+
        "\r\n"+    
        "  Internal:\r\n"+
        "    See documentation in the TCP/IP Stack APIs or http_net.h for details.\r\n"+
        "****************************************************************************/\r\n"+
        "uint8_t TCPIP_HTTP_NET_ConnectionUserAuthenticate(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const char *cUser, const char *cPass, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack);\r\n"+
        "#endif\r\n"+
        "\r\n"+     
        " // processing the HTTP buffer acknowledgment\r\n"+
        "void TCPIP_HTTP_NET_DynAcknowledge(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const void *buffer, const struct _tag_TCPIP_HTTP_NET_USER_CALLBACK *pCBack);\r\n"+
        "\r\n"+     
        "// processing the HTTP reported events\r\n"+
        "void TCPIP_HTTP_NET_EventReport(TCPIP_HTTP_NET_CONN_HANDLE connHandle, TCPIP_HTTP_NET_EVENT_TYPE evType, const void *evInfo, const struct _tag_TCPIP_HTTP_NET_USER_CALLBACK *pCBack);\r\n"+
        "\r\n"+     
        "// example of processing an SSI notification\r\n"+
        "// return false for standard processing of this SSI command by the HTTP module\r\n"+
        "// return true if the processing is done by you and HTTP need take no further action\r\n"+
        "bool TCPIP_HTTP_NET_SSINotification(TCPIP_HTTP_NET_CONN_HANDLE connHandle, TCPIP_HTTP_SSI_NOTIFY_DCPT *pSSINotifyDcpt, const struct _tag_TCPIP_HTTP_NET_USER_CALLBACK *pCBack);\r\n"+
        "\r\n"+ 
        "/****************************************************************************\r\n"+
        "  Section:\r\n"+
        "    Application Dynamic Variables processing functions.\r\n"+
        "    For easy processing and facilitating of the transfer from the old style of\r\n"+
        "    processing the dynamic variables with pre-defined functions,\r\n"+
        "    the new dynamic variables functions maintain the old name and\r\n"+
        "    a table showing the correspondence between the dynamic variable name\r\n"+
        "    and the function that processes that variable i smaintained in this\r\n"+
        "    coming HTTP_APP_DynVarTbl[].\r\n"+
        "    Note that this is just an example.\r\n"+
        "    The application could opt for any type of proccessing it needs to do at run time.\r\n"+
        "\r\n" +    
        "    See http_net.h for details regarding each of these functions.\r\n"+
        "****************************************************************************/\r\n\r\n"+

        "// application HTTP dynamic variables processing function\r\n"+
        "typedef TCPIP_HTTP_DYN_PRINT_RES (*HTTP_APP_DYNVAR_FNC)(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const TCPIP_HTTP_DYN_VAR_DCPT *vDcpt);\r\n"+
        "\r\n"+    
        "// an entry for the application processing HTTP dynamic variables\r\n"+
        "typedef struct HTTP_APP_DYNVAR_ENTRY\r\n"+
        "{\r\n"+
        "    const char *varName;        // name of the dynamic variable\r\n"+
        "    HTTP_APP_DYNVAR_FNC varFnc; // processing function\r\n"+
        "}HTTP_APP_DYNVAR_ENTRY;\r\n"+
        "\r\n"+    
        "// Number of buffers to be used by the app for dynamic variable callbacks\r\n"+
        "#define HTTP_APP_DYNVAR_BUFFERS_NO      4\r\n"+
        "\r\n"+    
        "// size of an allocated dynamic variable call back buffer\r\n"+
        "#define HTTP_APP_DYNVAR_BUFFER_SIZE     100\r\n"+
        "\r\n"+    
        "//An entry for the dynamic variables which is used during the dynamic variable processing\r\n"+
        "typedef struct HTTP_APP_DYNVAR_BUFFER\r\n"+
        "{\r\n"+
        "    uint16_t    busy;           // buffer is currently in process\r\n"+
        "    uint16_t    bufferSize;     // size of the associated buffer\r\n"+
        "    char        data[HTTP_APP_DYNVAR_BUFFER_SIZE];  // buffer for writing the dynamic variable callback content\r\n"+
        "}HTTP_APP_DYNVAR_BUFFER;\r\n"+
        "\r\n"+    
        "/****************************************************************************\r\n"+
        "  Section:\r\n"+
        "    Application initialization and HTTP registration.\r\n"+
        "    Here the application registers with the HTTP module the functions\r\n"+
        "    that will process the HTTP events (dynamic variables, SSI events, Post, Get, etc.).\r\n"+
        "    Note that without registering the process functions with HTTP, there won't be any web page processing.\r\n"+
        "    There is no default processing for a web page!\r\n"+
        "\r\n"+    
        "    See http_net.h for details regarding each of these functions.\r\n"+
        "****************************************************************************/\r\n"+
        "void HTTP_APP_Initialize(void);\r\n"+
        "\r\n"+    
        "// helper to get one of the application's dynamic buffer that are used in the\r\n"+
        "// dynamic variables processing\r\n"+
        "HTTP_APP_DYNVAR_BUFFER *HTTP_APP_GetDynamicBuffer(void);\r\n\r\n\r\n";
    String HTTPPRINT_NET_H_FOOTER =
        "#endif /* _HTTP_NET_PRINT_H */\r\n";

    
    String HTTPPRINT_NET_C_HEADER =
        "/*********************************************************************\r\n" +
        "* File Name: http_net_print.c \r\n" +
        "*\r\n"+
        "* Provides callback headers and resolution for user's custom\r\n" +
        "* HTTP NET Application.\r\n" +
        "*\r\n"+
        "* This file is automatically generated by the MPFS Utility\r\n" +
        "* ALL MODIFICATIONS WILL BE OVERWRITTEN BY THE MPFS GENERATOR\r\n" +
        "*\r\n"+        
        "*********************************************************************/\r\n\r\n" +
        "/*****************************************************************************\r\n" +
        " Copyright (C) 2012-2018 Microchip Technology Inc. and its subsidiaries.\r\n\r\n" +
        " Microchip Technology Inc. and its subsidiaries.\r\n\r\n" +
        " Subject to your compliance with these terms, you may use Microchip software\r\n" +
        " and any derivatives exclusively with Microchip products. It is your\r\n" +
        " responsibility to comply with third party license terms applicable to your\r\n" +
        " use of third party software (including open source software) that may\r\n" +
        " accompany Microchip software.\r\n\r\n" +
        " THIS SOFTWARE IS SUPPLIED BY MICROCHIP \"AS IS\". NO WARRANTIES, WHETHER\r\n" +
        " EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED\r\n" +
        " WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR\r\n" +
        " PURPOSE.\r\n" +
        " \r\n" +
        " IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE,\r\n" +
        " INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND\r\n" +
        " WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS\r\n" +
        " BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE\r\n" +
        " FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN\r\n" +
        " ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,\r\n" +
        " THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.\r\n" +
        " *****************************************************************************/\r\n\r\n" +
        "#include \"configuration.h\"\r\n" +
        "#include \"definitions.h\" \r\n" +
        "#include \"tcpip/tcpip.h\"\r\n"+
        "#include \"http_net_print.h\"\r\n";
        
    String HTTPPRINT_NET_C_MIDDLE =
        "/****************************************************************************\r\n"+
        "  Section:\r\n"+
        "    Application Dynamic Variables processing functions.\r\n"+
        "    For easy processing and facilitating of the transfer from the old style of \r\n"+
        "    processing the dynamic variables with pre-defined functions,\r\n"+
        "    the new dynamic variables functions maintain the old name and\r\n"+
        "    a table showing the correspondence between the dynamic variable name\r\n"+
        "    and the function that processes that variable i smaintained in this\r\n"+
        "    coming HTTP_APP_DynVarTbl[].\r\n"+
        "    Note that this is just an example.\r\n"+
        "    The application could opt for any type of proccessing it needs to do at run time.\r\n"+
        "\r\n"+    
        "    See http_net.h for details regarding each of these functions.\r\n"+
        "****************************************************************************/\r\n"+
        "\r\n"+
        "// table with the processed dynamic variables in this demo\r\n"+
        "static HTTP_APP_DYNVAR_ENTRY HTTP_APP_DynVarTbl[] = \r\n" +
        "{\r\n"+
        " // varName                      varFnc\r\n";    
              
    String HTTPPRINT_NET_C_FOOTER =
        "};\r\n"+
        "\r\n"+
            
        "// Function that processes the dynamic variables\r\n"+
        "// It uses the HTTP_APP_DynVarTbl[] for detecting which variable is currently processed\r\n"+
        "// and what function should be launched.\r\n"+
        "//\r\n"+
        "// Note: Again, this is just an example.\r\n"+
        "// Processing a large number of dynamic variables using this approach is highly inneficient\r\n"+
        "// and should be avoided.\r\n"+
        "// Better methods should be emplyed rather than linearly polling each variable name until the required name was found.\r\n"+
        "//\r\n"+
        "TCPIP_HTTP_DYN_PRINT_RES TCPIP_HTTP_NET_DynPrint(TCPIP_HTTP_NET_CONN_HANDLE connHandle, const TCPIP_HTTP_DYN_VAR_DCPT *vDcpt, const TCPIP_HTTP_NET_USER_CALLBACK *pCBack)\r\n"+
        "{\r\n"+
        "    int ix;\r\n"+
        "    HTTP_APP_DYNVAR_ENTRY *pEntry;\r\n"+
        "\r\n"+    
        "    // search for a dynamic variable name\r\n"+
        "    pEntry = HTTP_APP_DynVarTbl;\r\n"+
        "    for(ix = 0; ix < sizeof(HTTP_APP_DynVarTbl)/sizeof(*HTTP_APP_DynVarTbl); ++ix, ++pEntry)\r\n"+
        "    {\r\n"+
        "        if(strcmp(vDcpt->dynName, pEntry->varName) == 0)\r\n"+
        "        {   // found it\r\n"+
        "            return (*pEntry->varFnc)(connHandle, vDcpt);\r\n"+
        "        }\r\n"+
        "    }\r\n"+
        "\r\n"+    
        "    // not found; do nothing\r\n"+
        "    return TCPIP_HTTP_DYN_PRINT_RES_DONE;\r\n"+
        "}\r\n"+
        "\r\n"+    
        "static HTTP_APP_DYNVAR_BUFFER httpDynVarBuffers[HTTP_APP_DYNVAR_BUFFERS_NO];\r\n"+
        "\r\n"+    
        "// helper to get one of the application's dynamic buffer that are used in the\r\n"+
        "// dynamic variables processing\r\n"+
        "HTTP_APP_DYNVAR_BUFFER *HTTP_APP_GetDynamicBuffer(void)\r\n"+
        "{\r\n"+
        "    int ix;\r\n"+
        "    HTTP_APP_DYNVAR_BUFFER *pDynBuffer;\r\n"+
        "\r\n"+    
        "    pDynBuffer = httpDynVarBuffers;\r\n"+
        "    for(ix = 0; ix < sizeof(httpDynVarBuffers)/sizeof(*httpDynVarBuffers); ++ix, pDynBuffer++)\r\n"+
        "    {\r\n"+
        "        if(pDynBuffer->busy == 0)\r\n"+
        "        {\r\n"+
        "           pDynBuffer->busy = 1;\r\n"+
        "            return pDynBuffer;\r\n"+
        "        }\r\n"+
        "    }\r\n"+
        "    return 0;\r\n"+
        "}\r\n\r\n"+
        "/****************************************************************************\r\n"+
        "  Section:\r\n"+
        "    Application initialization and HTTP registration.\r\n"+
        "    Here the application registers with the HTTP module the functions\r\n"+
        "    that will process the HTTP events (dynamic variables, SSI events, Post, Get, etc.).\r\n"+
        "    Note that without registering the process functions with HTTP, there won't be any web page processing.\r\n"+
        "    There is no default processing for a web page!\r\n"+
        "\r\n"+    
        "    See http_net_print.h for details regarding each of these functions.\r\n"+
        "****************************************************************************/\r\n"+
        "void HTTP_APP_Initialize(void)\r\n"+
        "{\r\n"+
        "    int ix;\r\n"+
        "\r\n"+    
        "\r\n"+
        "    for(ix = 0; ix < sizeof(httpDynVarBuffers)/sizeof(*httpDynVarBuffers); ++ix)\r\n"+
        "    {\r\n"+
        "        httpDynVarBuffers[ix].busy = 0;\r\n"+
        "        httpDynVarBuffers[ix].bufferSize = HTTP_APP_DYNVAR_BUFFER_SIZE;\r\n"+
        "    }\r\n"+
        "\r\n"+    
        "    TCPIP_HTTP_NET_USER_CALLBACK appHttpCBack =\r\n"+
        "    {\r\n"+
        "        .getExecute = TCPIP_HTTP_NET_ConnectionGetExecute,              // Process the "+ "\""+"GET"+"\""+" command\r\n"+
        "        .postExecute = TCPIP_HTTP_NET_ConnectionPostExecute,            // Process the "+ "\""+"POST"+"\""+" command\r\n"+
        "        .fileAuthenticate = TCPIP_HTTP_NET_ConnectionFileAuthenticate,  // Process the file authentication\r\n"+
        "        .userAuthenticate = TCPIP_HTTP_NET_ConnectionUserAuthenticate,  // Process the user authentication\r\n"+
        "\r\n"+    
        "        .dynamicPrint = TCPIP_HTTP_NET_DynPrint,                        // Process the dynamic variable callback\r\n"+
        "        .dynamicAck = TCPIP_HTTP_NET_DynAcknowledge,                    // Acknowledgment function for when the dynamic variable processing is completed\r\n"+
        "        .eventReport = TCPIP_HTTP_NET_EventReport,                      // HTTP Event notification callback\r\n"+
        "\r\n"+    
        "        .ssiNotify = TCPIP_HTTP_NET_SSINotification,                    // SSI command calback\r\n"+
        "    };\r\n"+
        "\r\n" +    
        "    TCPIP_HTTP_NET_USER_HANDLE httpH = TCPIP_HTTP_NET_UserHandlerRegister(&appHttpCBack);\r\n"+
        "    if(httpH == 0)\r\n"+
        "    {\r\n"+
        "        SYS_CONSOLE_MESSAGE("+ "\"" + "APP: Failed to register the HTTP callback! \\r\\n" + "\""+ ");\r\n"+
        "    }\r\n"+
        "}\r\n\r\n";
        


/*
 * Collect the Dynamic variable in the HTTPPrint.idx file.
 */
    public DynVar(String path,boolean ifTcpipVersion6used)
    {
        this.projectDir = path;
        vars = new LinkedList<DynamicVariable>();
        tcpipHttpNetVersionused = ifTcpipVersion6used;
        // Read previous index file if it exists.
        File file_exists;
        FileInputStream inputFile;
        try
        {
            
            file_exists = new File(projectDir + "http_net_print.idx");
           
            if(file_exists.exists() && file_exists.length()>0)
            {
                inputFile = new FileInputStream(projectDir + "http_net_print.idx");
                
                DataInputStream in = new DataInputStream(inputFile);
                BufferedReader fin = new BufferedReader(new InputStreamReader(in));
                String s = fin.readLine();

                if (!s.contains("|"))
                {
                    while (s != null)
                    {
                        DynamicVariable dv = new DynamicVariable(s);
                        vars.add(dv);
                        s = fin.readLine();
                    }
                }
                fin.close();
            }
        }
        catch(IOException e)
        {
            // do nothing...just won't have old index information
        }
    }

    /// <summary>
    /// Parses and indexes a file for dynamic variables
    /// </summary>
    /// <param name="file">The MPFSFileRecord to parse</param>
    /// <returns>An MPFSFileRecord of indexes, or null if no variables were found</returns>
    public MPFSFileRecord Parse(MPFSFileRecord file,StringBuilder strLine)
    {
        int dynVarCntr=0;
        ByteArrayOutputStream resizeArray = new ByteArrayOutputStream();
        Matcher matches;
        Matcher ignore_matches = ignore_dynmicvar_parser.matcher(strLine);
        
        // add the ignored dynamic variable to the list which are part of the <code> and </code>
        while(ignore_matches.find())
        {
            // Get the matching string starts with <code> and ends with </code>
            String tempStr = ignore_matches.group();
            // find the length of the string
            int strLen = tempStr.length();
            int offset = 0;
            // get the location of the tempStr which starts with <code> with dynamic variable
            offset = strLine.indexOf(tempStr);
            // replace '~' to '#' and where this variable won't be used for dynamic processing.
            tempStr = tempStr.replaceAll("~", "#");
            // replace the old string with new string -
            // e.g - chnage "<code> ~myVariable~ </code>" to "<code> #myVariable# </code>"
            strLine.replace(offset, offset+strLen, tempStr);
        }
        matches = parser.matcher(strLine);
        while(matches.find())
        {
            int i = GetIndex(matches.group().replace(" ","").replace("~",""));
            
            resizeArray.write((byte)matches.start());
            resizeArray.write((byte)(matches.start()>>8));
            resizeArray.write((byte)(matches.start()>>16));
            resizeArray.write((byte)(matches.start()>>24));
            resizeArray.write((byte)i);
            resizeArray.write((byte)(i>>8));
            resizeArray.write((byte)(i>>16));
            resizeArray.write((byte)(i>>24));

            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 0));
            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 8));
            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 16));
            file.dynVarOffsetAndIndexID.addElement((byte)(matches.start() >> 24));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 0));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 8));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 16));
            file.dynVarOffsetAndIndexID.addElement((byte)(i >> 24));

            file.dynVarCntr = ++dynVarCntr;
            offSetCounter = offSetCounter + 8;
        }

        if(parseItrtn == (int)0x0)
        {
            file.fileRecordOffset = (int)0x0;
            offSetCounter = (int)0x0;
        }
        else
        {
            file.fileRecordOffset=tempFileRcrdLen;
        }
        if(file.dynVarCntr != 0)
        {
            file.fileRecordLength = 4 /* 4 bytes for file record length itself*/
                                    + 2 /*To store the hasIndex/isZipped flag*/
                                    //+(UInt32)file.FileName.Length
                                    + file.dynVarCntr * 8;

            tempFileRcrdLen += file.fileRecordLength;

            parseItrtn++;
        }

        // Determine if any matches were made
        if (resizeArray.size() == 0)
        {
            return null;
        }
        else
        {
            // Set up new file record
            MPFSFileRecord idxFile = new MPFSFileRecord();
            idxFile.SetFileName("");   //.FileName = "";
            idxFile.SetFiledate(file.fileDate);
            idxFile.isIndex = true;
            idxFile.data = resizeArray.toByteArray();
            idxFile.fileSizeLen = resizeArray.size();
            return idxFile;
        }
    }

    /// <summary>
    /// Writes out HTTPPrint.h and HTTPPrint.idx if necessary
    /// </summary>
    /// <returns>TRUE if the files were written, FALSE if no changes are needed</returns>
    public boolean WriteIndices()
    {
        // Determine if an update is necessary
        boolean isChanged = false;
        File httpFileIdx = null;
        String temp_str;
/* TODO [HS] - The following code can be reused for idx file recreation
        for(DynamicVariable dv : vars)
        {
            if ((dv.getWasUsed() && dv.getCount() == 0) ||
                (!dv.getWasUsed() && dv.getCount() != 0))
            {
                isChanged = true;
                break;
            }
        }
        if (!isChanged)
        {
            return false;
        }
*/
        // Write out http_net_print.idx        
        httpFileIdx = new File(projectDir +"http_net_print.idx");
       
        try{
        FileOutputStream file_header_output=null ;
        DataOutputStream data_header_out = null;
        BufferedWriter fout_header = null;
        
        FileOutputStream file_source_output=null ;
        DataOutputStream data_source_out = null;
        BufferedWriter fout_source = null;
        
        FileOutputStream file_idx_output = new FileOutputStream(httpFileIdx);
        DataOutputStream data_idx_out = new DataOutputStream (file_idx_output);
        BufferedWriter fout_idx = new BufferedWriter(new OutputStreamWriter(data_idx_out));
        

        for(DynamicVariable dv : vars)
        {
            if (dv.getCount() > 0)
            {
                fout_idx.write('+');
            }
            fout_idx.write(dv.GetName());
            fout_idx.write('\n');
        }
        fout_idx.flush();
        fout_idx.close();

        // Begin writing HTTPPrint.h
        if(tcpipHttpNetVersionused)
        {
            file_header_output = new FileOutputStream(projectDir + "http_net_print.h");
            file_source_output = new FileOutputStream(projectDir + "http_net_print.c");
        }

        data_header_out = new DataOutputStream (file_header_output);
        fout_header = new BufferedWriter(new OutputStreamWriter(data_header_out));
        data_source_out = new DataOutputStream (file_source_output);
        fout_source = new BufferedWriter(new OutputStreamWriter(data_source_out));
        
        // http_net_print.h  write header details
        fout_header.write(HTTPPRINT_NET_H_HEADER);
        
        // http_net_print.c write header details
        fout_source.write(HTTPPRINT_NET_C_HEADER);
        // write the Middle one of the http_net_print.c file
        fout_source.write(HTTPPRINT_NET_C_MIDDLE);

        // Write the prototypes
        List<String> prototypes = new ArrayList<String>();
        Pattern rGetParts = Pattern.compile("([A-Za-z0-9_]{0,40})(\\(([A-Za-z0-9_,]*)\\))?");
        for(DynamicVariable dv : vars)
        {
            if (dv.GetName().startsWith("inc:") || dv.getCount() == 0)
            {
                continue;
            }
            Matcher m = rGetParts.matcher(dv.GetName());
            if(m.find())
            {
                if (prototypes.contains(m.group(1)))
                {
                    continue;
                }

                // Add the prototype
                prototypes.add(m.group(1));
                temp_str = "TCPIP_HTTP_DYN_PRINT_RES TCPIP_HTTP_Print_" + m.group(1) + "(";

                fout_header.write(temp_str);
                temp_str = "TCPIP_HTTP_NET_CONN_HANDLE connHandle, const TCPIP_HTTP_DYN_VAR_DCPT *vDcpt";
                fout_header.write(temp_str);
                fout_header.write(");\r\n");
                // update http_net_print.c file with varName and var function
                temp_str = "{" + "\""+ m.group(1) + "\"" + "," + "\t\t\t\t\t" + "TCPIP_HTTP_Print_" + m.group(1);
                fout_source.write(temp_str);
                fout_source.write("},\r\n");
            }
        }

       // header file middle one
        fout_header.write(HTTPPRINT_NET_H_MIDDLE);    
        fout_header.write(HTTPPRINT_NET_H_FOOTER);
        fout_source.write(HTTPPRINT_NET_C_FOOTER);
        fout_source.flush();
        fout_source.close();
        fout_header.flush();
        fout_header.close();
        
        }catch (IOException e){}
        return true;
    }

    /// <summary>
    /// Finds the index of a dynamic variable, or creates a new one
    /// </summary>
    /// <param name="name"></param>
    /// <returns>The index of the dynamic variable</returns>
    private int GetIndex(String name)
    {
        int count = 0;
        // Search for the dynamic variable
        DynamicVariable dv = new DynamicVariable(name);

        int i = vars.indexOf(dv);
        // If not found, add a new one
        if (i == -1)
        {
            vars.add(dv);
            i = vars.size()-1;
        }
        // Mark as used and return the index
        count = vars.get(i).getCount();
        vars.get(i).setCount(++count);

        return i;
    }
}

/*
 * Dynamic variable class to count and find out the instance how many times
 * it is being used.
 */
class DynamicVariable
{
    private String name;
    private boolean wasUsed;
    private int count;

    /// <summary>
    /// Gets or sets the name of this DynamicVariable
    /// </summary>
    public String GetName()
    {
        return this.name;
    }

    public void SetName(String value)
    {
        this.name = value;
    }

    /// <summary>
    /// Indicates if this specific instance was previously used
    /// </summary>
    public boolean getWasUsed()
    {
       return this.wasUsed;
    }
    public void setWasUsed(boolean value)
    {
        this.wasUsed = value;
    }
    /// <summary>
    /// Indicates how many times this instance is used
    /// </summary>
    public int getCount()
    {
       return this.count;
    }

    public void setCount(int value)
    {
       this.count = value;
    }
    private long _offsetCntr = 0;
    public long getOffsetCntr()
    {
        return this._offsetCntr;
    }

    public void setOffsetCntr(long value)
    {
         this._offsetCntr = value;
    }

    public DynamicVariable(String name)
    {
        String regEx = "[\\ \\+]";
        this.wasUsed = name.startsWith("+");
       
        this.name = name.replaceFirst(regEx,"");
        this.count = 0;
    }

    public boolean equals(Object obj)
    {
        if (obj instanceof DynamicVariable)
        {
            return ((DynamicVariable)obj).GetName().contentEquals(this.name);
        }
        else
        {
            return false;
        }
    }

    public int hashCode()
    {
        return this.name.hashCode();
    }
}
